package com.alks.function.service.impl.procurement;

import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.dto.SysUserTokenDTO;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.service.RedisService;
import com.alks.common.utils.DateUtils;
import com.alks.common.utils.beanutils.ObjectUtils;
import com.alks.common.utils.excelUtils.CellStyleBuild;
import com.alks.common.utils.excelUtils.ExcelPoiUtils;
import com.alks.common.utils.excelUtils.ExcelUtils;
import com.alks.entity.data.entity.*;
import com.alks.entity.data.enums.CompanyEnum;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.MpPurDisDto;
import com.alks.function.data.dto.chengKong.produce.PcLotDetailDto;
import com.alks.function.data.dto.chengKong.produce.PcLotUsageDto;
import com.alks.function.data.dto.procurement.CleanDataDto;
import com.alks.function.data.dto.procurement.LotNoDto;
import com.alks.function.data.dto.procurement.PurchaseOrderDto;
import com.alks.function.data.dto.procurement.SummaryMaterialsDto;
import com.alks.function.data.request.procurement.*;
import com.alks.function.data.request.stockdept.pcfactorystockwork.MyOrdUpRequest;
import com.alks.function.mapper.MpPurDisMapper;
import com.alks.function.mapper.SdCompanyMapper;
import com.alks.function.mapper.chengKong.PcLotHeadMapper;
import com.alks.function.mapper.common.BackMapper;
import com.alks.function.mapper.procurement.*;
import com.alks.function.mapper.stockdept.pcfactorystockquery.*;
import com.alks.function.service.common.BackService;
import com.alks.function.service.procurement.MaterialClearanceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.alks.entity.data.enums.ResultCodeEnum.IN_IS_EMPTY;

@Primary
@Service
@Slf4j
@RequiredArgsConstructor
public class MaterialClearanServiceImpl extends ServiceImpl<SD_SQ_MpPurDisMapper, MpPurDis>  implements MaterialClearanceService {

    @Autowired
    private MaterialClearanceMapper materialClearanceMapper;

    @Autowired
    private SummaryOperationMapper summaryOperationMapper;

    @Autowired
    private  RedisService redisService;

    @Autowired
    private  SD_SQ_MpPurDisMapper disMapper;

    @Autowired
    private SD_SQ_MpPurMtlLotMapper mtlLotMapper;

    @Autowired
    private SD_SQ_MpMtlSumMapper sumMapper;

    @Autowired
    private SD_SQ_MpMtlLotMapper lotMapper;

    @Autowired
    private BackMapper backMapper;

    @Autowired
    private PurCompanyMapper purMapper;

    @Autowired
    private PurCompanyMapper2 purMapper2;

    @Autowired
    private PcLotHeadMapper pcLotHeadMapper;

    @Autowired
    private SD_SQ_MpMtlSubMapper subMapper;

    @Autowired
    private PcLotUsageChgMapper pcLotUsageChgMapper;

    @Autowired
    private PcLotUsageChgMapper PcLotHeadMapper;

    @Autowired
    private PcRecDetailMapper pcRecDetailMapper;

    @Autowired
    private BackService backService;



    /**
     * 指令明细查询
     * @param lotNo
     * @return
     */
    @Override
    @AutoPageAop
    public ResponseInfo getAllLotNoList(String lotNo) {
        String companyId = UserIdThread.get().getCompanyId();
        //List<String> lotNoList = materialClearanceMapper.getAllLotNoList(lotNo,companyId);
        List<String> lotNoList = materialClearanceMapper.getAllLotNoList2(lotNo,companyId);

        PageInfo list = new PageInfo(lotNoList);
        HashMap map = new HashMap<>();
        map.put("lotNoList", lotNoList);
        map.put("total", list.getTotal());
        return ResponseInfo.ok(map);
    }

    /**
     * 指令明细查询
     * @param request
     * @return
     */
    @Override
    @AutoPageAop
    public ResponseInfo getLotNoList(LotNoRequest request) {
        //shiqian TODO  :我写的sql多两条数据
        String companyId = UserIdThread.get().getCompanyId();
        request.setCompanyId(companyId);
        List<LotNoDto> lotNoList = materialClearanceMapper.getLotNoList(request);

        PageInfo list = new PageInfo(lotNoList);
        HashMap map = new HashMap<>();
        map.put("lotNoList", lotNoList);
        map.put("total", list.getTotal());
        return ResponseInfo.ok(map);
    }

    /**
     * 汇总材料查询
     * @param request
     * @return
     */
    @Override
    //@AutoPageAop
    public ResponseInfo getSummaryMaterialsList(LotNoRequest2 request) {
        String companyId = UserIdThread.get().getCompanyId();
        request.setCompanyId(companyId);

        //判断
        //如果指令未审核提示该指令未审核，或者该指令不存在
        if(StringUtils.isNotBlank(request.getLotNo())){
            backService.getRyLotCheck(request.getLotNo());
        }

        //List<SummaryMaterialsDto> summaryList = materialClearanceMapper.getAllSummaryMaterialsList(request);
        //查询最新的bom的数据为主体
        List<SummaryMaterialsDto> summaryList = materialClearanceMapper.getAllSummaryMaterialsList2(request);

        //查询采购表有但是订单表没有的材料
        List<SummaryMaterialsDto> summaryList2 = materialClearanceMapper.getAllSummaryMaterialsList3(request);

        summaryList.addAll(summaryList2);

        // 假设 SummaryMaterialsDto 中有 getLotNo() 和 getMtlNo() 方法
        summaryList.sort(
                Comparator.comparing(
                        SummaryMaterialsDto::getLotNo,
                        Comparator.nullsLast(String::compareTo).reversed()  // 降序
                ).thenComparing(
                        SummaryMaterialsDto::getMtlNo,
                        Comparator.nullsLast(String::compareTo)             // 升序
                )
        );

        // 获取分页参数（带默认值）
        int pageNum = request.getPageNum() == null ? 1 : request.getPageNum();
        int pageSize = request.getPageSize() == null ? 10 : request.getPageSize();

        // 总记录数
        int total = summaryList.size();

        // 计算起止索引
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, total);

        // 分页结果（新建列表，避免 subList 视图副作用）
        List<SummaryMaterialsDto> pageList = Collections.emptyList();
        if (start < total && !summaryList.isEmpty()) {
            pageList = new ArrayList<>(summaryList.subList(start, end));
        }

        // 构造返回结果
        HashMap<String, Object> map = new HashMap<>();
        map.put("lotNoList", pageList);
        map.put("total", total);
        return ResponseInfo.ok(map);

        //PageInfo list = new PageInfo(summaryList);
        //HashMap map = new HashMap<>();
        //map.put("lotNoList", summaryList);
        //map.put("total", list.getTotal());
        //return ResponseInfo.ok(map);
    }


    /**
     * 我的订购单查询
     * @param request
     * @returnc
     */
    @Override
    @AutoPageAop
    public ResponseInfo getPurchaseOrderList(PurchaseOrderRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        request.setCompanyId(companyId);
        //request.setSysUser(name);
        if(request.getUserFlag() == 2){
            if(StringUtils.isBlank(request.getSysUser())){
                request.setSysUser(null);
            }else {
                request.setSysUser(request.getSysUser());
            }
        }else{
            request.setSysUser(UserIdThread.get().getUserName());
        }

        List<PurchaseOrderDto> orderList = materialClearanceMapper.getPurchaseOrderInHzAndCyOrderMtl(request);

        PageInfo summaryPageInfo = new PageInfo(orderList);
        HashMap<String, Object> map = new HashMap<>();
        map.put("lotNoList", orderList);
        map.put("total", summaryPageInfo.getTotal());
        return ResponseInfo.ok(map);
    }

    /**
     * 所有订购单查询
     * @param request
     * @return
     */
    @Override
    @AutoPageAop
    public ResponseInfo getAllPurchaseOrderList(PurchaseOrderRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        request.setCompanyId(companyId);

        List<PurchaseOrderDto> orderList = materialClearanceMapper.getPurchaseOrderInHzAndCyOrderMtl(request);

        PageInfo summaryPageInfo = new PageInfo(orderList);
        HashMap<String, Object> map = new HashMap<>();
        map.put("lotNoList", orderList);
        map.put("total", summaryPageInfo.getTotal());
        return ResponseInfo.ok(map);
    }

    /**
     * 我的订购单：编辑
     * @param list
     * @return
     */
    @Override
    @Transactional
    public ResponseInfo updatePurchaseOrder(List<PurchaseOrderDto> list) {
        //可以编辑：多够量、厂商代码和名称、需求交期、厂商回复交期、采购备注、请购备注
        //如果已经订购：厂商代码和名称、需求交期、厂商回复交期不可编辑

        /*获取基础数据*/
        String companyId = UserIdThread.get().getCompanyId();
        String name = UserIdThread.get().getUserName();
        if(ObjectUtils.isEmpty(list)){
            throw new ServiceErrorException("请选择记录！");
        }

        for (PurchaseOrderDto dto : list) {
            dto.setSysUser(name);
            dto.setCompanyId(companyId);
            // 计算 purQty
            float purQty = (dto.getQty() == null ? 0 : dto.getQty()) +
                    (dto.getMinusQty() == null ? 0 : dto.getMinusQty()) +
                    (dto.getOverQty() == null ? 0 : dto.getOverQty());
            dto.setPurQty(purQty);
        }
        int count = disMapper.batchUpdateOrderByMaterialClearance(list);
        if (count > 0) {
            return ResponseInfo.ok("成功更新 " + count + " 条记录！");
        }else{
            throw new ServiceErrorException("更新失败或无记录更新！");
        }
    }

    /**
     * 我的订购单：单条编辑
     * @return
     */
    @Override
    @Transactional
    public ResponseInfo updatePurchaseOrder2(PurchaseOrderDto dto) {
        //可以编辑：多购量，厂商代码和名称、需求交期、厂商回复交期、采购备注、请购备注--,预加量
        //如果已经订购：需求交期、厂商回复交期不可编辑--多购量，预加量，采购备注

        /*获取基础数据*/
        String companyId = UserIdThread.get().getCompanyId();
        String name = UserIdThread.get().getUserName();
        if(dto == null){
            throw new ServiceErrorException("请选择记录！");
        }

        dto.setSysUser(name);
        dto.setCompanyId(companyId);
        // 计算 purQty
        float purQty = (dto.getQty() == null ? 0 : dto.getQty()) +
                (dto.getMinusQty() == null ? 0 : dto.getMinusQty()) +
                (dto.getOverQty() == null ? 0 : dto.getOverQty());
        dto.setPurQty(purQty);

        try {

        /*写入数据*/
        //1.修改:材料暂收表      MP_PUR_DIS
        int count1 = disMapper.updateFdPurDisAdd(dto);
        log.info("修改:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);

            //4.只有已经下单的走这条路******
            //4.修改：材料指令订购单 MP_PUR_MTL_LOT
        Boolean a = dto.getPurFlag() != null && dto.getPurFlag().equals("Y");
            if(a){
                int count2 = mtlLotMapper.updatePur(dto);
                log.info("修改：材料指令订购单       MP_PUR_MTL_LOT 成功，影响行数：{}", count2);
                if (count1 > 0 && count2 > 0) {
                    return ResponseInfo.ok("成功更新");
                }else{
                    throw new ServiceErrorException("更新失败");
                }
            }

        return ResponseInfo.ok("更新成功");

        }catch (Exception e){
            throw new ServiceErrorException("更新失败");
        }
    }

    /**
     * 我的订购单：批量改厂商
     * @param request
     * @return
     */
    @Override
    public ResponseInfo updatePurchaseOrderBatch(PurchaseOrderRequest2 request) {
        /*获取基础数据*/
        if(ObjectUtils.isEmpty(request.getList())){
            throw new ServiceErrorException("请选择记录！");
        }

        int count = disMapper.batchUpdateOrderOfVendor(request.getList(),request.getVendorNo(),request.getVendorName());
        if (count > 0) {
            return ResponseInfo.ok("更改厂商成功");
        }else{
            throw new ServiceErrorException("更改厂商失败");
        }
    }

    /**
     * 形成订购单
     * @param r
     * @return
     */
    @Override
    @Transactional
    public ResponseInfo makePurchaseOrder(LotNoRequest4 r) {
        // 1.如果是批量形成订购单，要判断厂商是否一样。如果不一致，报错：存在多个厂商
        List<MyOrdUpRequest> request = r.getRequest();  //页面上的数据集合
        //获取年月日的时间
        LocalDate now = LocalDate.now();
        //判空
        if(ObjectUtils.isEmpty(request)){
            throw new ServiceErrorException("请选择记录！");
        }
        //已经形成订购单的不能在生成订购单
        boolean b = request.stream().anyMatch(d -> StringUtils.isNotEmpty(d.getPurFlag()) && d.getPurFlag().equals("Y"));
        if (b) {
            throw new ServiceErrorException("存在已形成订购单的记录，请检查！");
        }

        //存在多个厂商
        long countVendorNo = request.stream()
                .map(MyOrdUpRequest::getVendorNo)
                .filter(vendorNo -> vendorNo != null && !vendorNo.isEmpty())// 过滤掉空字符串
                .distinct()
                .count();
        if (r.getVendorNo() == null && countVendorNo > 1) {
            throw new ServiceErrorException("存在多个厂商！");
        }
        // 判断批量厂商记录为空或者单条厂商
        boolean hasEmptyVendorNo = request.stream()
                .anyMatch(d -> d.getVendorNo() == null || d.getVendorNo().isEmpty());        // 检查是否存在空的 vendorNo
        if (r.getVendorNo() == null && hasEmptyVendorNo) {
            throw new ServiceErrorException("有厂商记录为空,请检查！");
        }
        //批量的需求时期为空或者单条的厂商回复交期交期为空
        boolean result = request.stream()
                .map(MyOrdUpRequest::getInDate)
                .anyMatch(Objects::isNull) && r.getRequiredDate() == null;
        if(r.getRequiredDate() == null && result) {
            throw new ServiceErrorException("记录交期为空！");
        }

        //2.订购单号生成
        /*生成订购单*/
        String companyId = UserIdThread.get().getCompanyId();
        String time = "yyMMddHH";
        String key = "MaterialClearance/makePurchaseOrder" + companyId + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMM"));
        //String key = "MaterialClearance/makePurchaseOrder" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMM"));//自增数字里面加上年月; //采购要求国内国外的订购单前缀都是RV，所有现在不能用公司作为键了
        String prefix = generatePrefix(key, "5", time);
        String k = CompanyEnum.updateId(companyId) + "P";
        String purNo =  k + prefix;

        //shiqian TODO  :  MP_PUR_MTL_LOT 的deliveyate

        //3.可以批量需求日期+厂商
        request.forEach(ord -> {
            //厂商
            ord.setVendorNo(r.getVendorNo()!= null ? r.getVendorNo() : ord.getVendorNo());
            ord.setVendorName(r.getVendorName()!= null ? r.getVendorName() : ord.getVendorName());
            // 需求交期和厂商回复交期
            ord.setVendorDate(r.getRequiredDate() != null ? r.getRequiredDate() : ord.getVendorDate());
            ord.setInDate(r.getRequiredDate() != null ? r.getRequiredDate() : ord.getInDate());
            //订单
            ord.setPurNo(purNo);
            ord.setCompanyId(companyId);
            ord.setPurDate(now);
        });

        try {
        //4.写入数据库
        //更新：材料暂收表 MP_PUR_DIS
        int count1 = disMapper.creatPurUpdate1(request);
        //写入：材料指令订购单 MP_PUR_MTL_LOT
        int count2 = mtlLotMapper.creatPurUpdate1(request);

        if(count1 > 0 && count2 > 0){
            return ResponseInfo.ok("形成订购单成功,订购单号：" + purNo);
        }else{
            throw new ServiceErrorException("形成订购单失败或无记录形成！");
        }
        }catch (Exception e){
            log.error("形成订购单过程中发生异常，请检查日志：",e);
            throw new ServiceErrorException("形成订购单过程中发生异常，请检查日志！");
       }
    }

    ///**
    // * 单行取消订购单（已订购订单到批处理）
    // * @param request
    // * @return
    // */
    //@Override
    //@Transactional
    //public ResponseInfo backPurchaseOrder(LotNoRequest6 request) {
    //    /*判断*/
    //    if (StringUtils.isEmpty(request.getPurFlag())) {
    //        throw new ServiceErrorException("该记录未下单，无法取消订购！");
    //    }
    //
    //    /*获取基础数据*/
    //    String companyId = UserIdThread.get().getCompanyId();
    //    request.setCompanyId(companyId);
    //
    //    try {
    //        /*删除数据*/
    //        //删除:材料暂收表      MP_PUR_DIS
    //        int count1 = disMapper.fdPurDisDelete(request);
    //        log.info("删除:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);
    //
    //        //删除:材料汇总表      MP_MTL_SUM
    //        int count2 = sumMapper.fdPurDisDelete(request);
    //        log.info("删除:材料汇总表      MP_MTL_SUM 成功，影响行数：{}", count2);
    //
    //        //删除：指令数据       MP_MTL_LOT
    //        int count3 = lotMapper.fdPurDisDelete(request);
    //        log.info("删除：指令数据       MP_MTL_LOT 成功，影响行数：{}", count3);
    //        //subMapper.fdPurDisAdd(request);   //只有贴合走此逻辑
    //
    //        //删除：材料指令订购单 MP_PUR_MTL_LOT
    //        int count7 = mtlLotMapper.deletePur(request);
    //        log.info("删除：材料指令订购单       MP_PUR_MTL_LOT 成功，影响行数：{}", count7);
    //
    //        boolean b1 = false;
    //        boolean b2 = false;
    //        boolean b3 = false;
    //        //汇总的数据
    //        if(request.getPurType().equals("汇总")){
    //            //更新回原先的汇总数据
    //            int count4 = summaryOperationMapper.pc042UpdateBack(request);
    //            b1 = count4 > 0;
    //            log.info("更新:材料汇总指令 pc042 成功，影响行数：{}", count4);
    //        }else{
    //            //退回:   PC_LOT_USAGE_CHG    PC_LOT_USAGE_FIT_CHG
    //            // 先把数据查出来
    //            int count5 = pcLotUsageChgMapper.updateBackPcLotUsageChgByPur(request);
    //            int count6 = pcLotUsageChgMapper.updatBackPcLotUsageFitChgByPur(request);
    //            b2 = count5 > 0 || count6 > 0;
    //            log.info("更新:PC_LOT_USAGE_CHG 数据更新成功，影响行数：{}", count5);
    //            log.info("更新:PC_LOT_USAGE_FIT_CHG 数据更新成功，影响行数：{}", count6);
    //        }
    //        b3 = b1 || b2;
    //
    //        if(count1 > 0 && count2 > 0 && count3 > 0 && count7 > 0 && b3){
    //            return ResponseInfo.ok("单行取消订购单成功");
    //        }else{
    //            throw new ServiceErrorException("退回请购单发生异常，请检查日志!");
    //        }
    //    }catch (Exception e){
    //        log.error("单行取消订购单中发生异常，请检查日志",e);
    //        throw new ServiceErrorException("单行取消订购单发生异常，请检查日志!");
    //    }
    //}
    /**
     * 单行取消订购单（已订购订单到批处理）
     * @param request
     * @return
     */
    @Override
    @Transactional
    public ResponseInfo backPurchaseOrder(LotNoRequest6 request) {
        /*判断*/
        if (StringUtils.isEmpty(request.getPurFlag())) {
            throw new ServiceErrorException("该记录未下单，无法取消订购！");
        }

        /*获取基础数据*/
        String companyId = UserIdThread.get().getCompanyId();
        request.setCompanyId(companyId);

        try {
            /*删除数据*/
            //删除:材料暂收表      MP_PUR_DIS
            int count1 = disMapper.fdPurDisDelete(request);
            log.info("删除:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);

            //删除:材料汇总表      MP_MTL_SUM
            int count2 = sumMapper.fdPurDisDelete(request);
            log.info("删除:材料汇总表      MP_MTL_SUM 成功，影响行数：{}", count2);

            //删除：指令数据       MP_MTL_LOT
            int count3 = lotMapper.fdPurDisDelete(request);
            log.info("删除：指令数据       MP_MTL_LOT 成功，影响行数：{}", count3);
            //subMapper.fdPurDisAdd(request);   //只有贴合走此逻辑

            //删除：材料指令订购单 MP_PUR_MTL_LOT
            int count7 = mtlLotMapper.deletePur(request);
            log.info("删除：材料指令订购单       MP_PUR_MTL_LOT 成功，影响行数：{}", count7);

            if(count1 > 0 && count2 > 0 && count3 > 0 && count7 > 0 ){
                return ResponseInfo.ok("单行取消订购单成功");
            }else{
                throw new ServiceErrorException("退回请购单发生异常，请检查日志!");
            }
        }catch (Exception e){
            log.error("单行取消订购单中发生异常，请检查日志",e);
            throw new ServiceErrorException("单行取消订购单发生异常，请检查日志!");
        }
    }

    /**
     * 置空订购信息（已订购订单取消订购）
     * @param request
     * @return
     */
    @Override
    @Transactional
    public ResponseInfo cancelPurchaseOrder(LotNoRequest6 request) {
        /*判断*/
        if ( ObjectUtils.isEmpty(request.getPurFlag())) {
            throw new ServiceErrorException("该记录未下单，无法取消订购！");
        }

        /*获取基础数据*/
        String companyId = UserIdThread.get().getCompanyId();
        request.setCompanyId(companyId);

        try {
            /*删除数据*/
            //更新:材料暂收表purFlag变成空      MP_PUR_DIS
            int count1 = disMapper.fdPurDisUpdateNull(request);
            log.info("删除:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);

            //删除：材料指令订购单 MP_PUR_MTL_LOT
            int count2 = mtlLotMapper.deletePur(request);
            log.info("删除：材料指令订购单       MP_PUR_MTL_LOT 成功，影响行数：{}", count2);

            if(count1 > 0 && count2 > 0 ){
                return ResponseInfo.ok("置空订购信息成功");
            }else{
                throw new ServiceErrorException("置空订购信息失败");
            }
        }catch (Exception e){
            log.error("置空订购信息中发生异常，请检查日志",e);
            throw new ServiceErrorException("置空订购信息发生异常，请检查日志!");
        }
    }

    /**
     * 单行取消订购单（已订购订单到批处理）-批量
     * @param request
     * @return
     */
//    @Override
//    public ResponseInfo backPurchaseOrderBatch(List<LotNoRequest6> request) {
//        return null;
//    }

    /**
     * 订购取消:取消处理（已订购订单订单数量更改（只能变少））
     * @param request
     * @return
     */
    @Override
    @Transactional
    public ResponseInfo cancelPurchaseOrderNumber(LotNoRequest7 request) {
        /*判断*/
        if(StringUtils.isEmpty(request.getPurNo())){
            throw new ServiceErrorException("订购单号为空，不能取消订购！");
        }
        //请输入数量
        if(request.getQty2() == null && request.getMinusQty2() == null){
            throw new ServiceErrorException("请输入数量！");
        }
        if(request.getCancelQty() == null ){
            throw new ServiceErrorException("取消数量为空！");
        }
        // 处理 null 值的情况
        Float qty = request.getQty() == null ? 0f : request.getQty();
        Float qty2 = request.getQty2() == null ? 0f : request.getQty2();
        Float overQty = request.getOverQty() == null ? 0f : request.getOverQty();
        Float minusQty = request.getMinusQty() == null ? 0f : request.getMinusQty();
        Float minusQty2 = request.getMinusQty2() == null ? 0f : request.getMinusQty2();
        Float cancelQty = request.getCancelQty() == null ? 0f : request.getCancelQty();
        Float cancelCanQty = request.getCancelCanQty() == null ? 0f : request.getCancelCanQty();
        Float cancelDidQty = request.getCancelDidQty() == null ? 0f : request.getCancelDidQty();
        // 不能超过正单数量
        if (qty2 > qty) {
            throw new ServiceErrorException("不能超过正单数量！");
        }
        // 不能超过多购数量
        if (minusQty2 > minusQty) {
            throw new ServiceErrorException("不能超过多购数量！");
        }
        if(request.getFunction() == 2){
            // 超过已取消数量
            if (cancelQty > cancelDidQty) {
                throw new ServiceErrorException("超过已取消数量！");
            }
        }else if(request.getFunction() == 1){
            // 不能超过可取消数量
            if (cancelQty > cancelCanQty) {
                throw new ServiceErrorException("超过可取消数量！");
            }
        }

        /*获取基础数据*/
        String companyId = UserIdThread.get().getCompanyId();
        request.setCompanyId(companyId);

        /*查询数据*/
        //查询该材料入库数量
        PcRecDetail mtl = pcRecDetailMapper.getMtlInQty(request);
        if(mtl != null && mtl.getQty()!= null){
            BigDecimal q = mtl.getQty();
            float backQty = q.floatValue();
            request.setBackQty(backQty);
        }else{
            request.setBackQty(0f);
        }

        //取消数量变更
        //1.如果是“取消操作”，增加数量
        //1.如果是“还原操作”，减少数量
        if (request.getFunction() == 1) {
            request.setCancelQty(cancelQty + cancelDidQty);
        } else if (request.getFunction() == 2) {
            request.setCancelQty(cancelQty - cancelDidQty);
        }

        float purQty = qty + minusQty + overQty - cancelQty ;
        request.setPurQty(purQty);
        try {
            /*删除数据*/
            //更新:材料暂收表      MP_PUR_DIS
            int count1 = disMapper.fdPurDisUpdateNum(request);
            log.info("更新:材料暂收表数量      MP_PUR_DIS 成功，影响行数：{}", count1);

            //更新：材料指令订购单数量 MP_PUR_MTL_LOT
            int count2 = mtlLotMapper.updateNumPur(request);
            log.info("更新：材料指令订购单数量       MP_PUR_MTL_LOT 成功，影响行数：{}", count2);

            if(count1 > 0 && count2 > 0 ){
                return ResponseInfo.ok("取消处理成功");
            }else{
                throw new ServiceErrorException("取消处理失败");
            }
        }catch (Exception e){
            log.error("取消处理中发生异常，请检查日志",e);
            throw new ServiceErrorException("取消处理发生异常，请检查日志!");
        }
    }

//    /**
//     * 请求批处理
//     */
//    @Override
//    @Transactional
//    public ResponseInfo getBatchProcess(List<LotNoRequest5> r) {
//        /*判断*/
//        if (r == null || r.isEmpty()) {
//            throw new ServiceErrorException("请选择要下单的数据");
//        }
//        //订购数量为负的，不能请购！
//        //boolean a = r.stream().anyMatch(item -> item.getCyQty() != null && item.getCyQty().compareTo(BigDecimal.ZERO) <= 0);
//        //if (a) {
//        //    throw new ServiceErrorException("有记录订购数量为负数或零，请检查！");
//        //}
//        boolean a = r.stream().anyMatch(item -> item.getCyQty() != null && item.getCyQty().compareTo(BigDecimal.ZERO) == 0);
//        if (a) {
//            throw new ServiceErrorException("有记录订购数量零，请检查！");
//        }
//
//        /*获取基础数据*/
//        String userName = UserIdThread.get().getUserName();
//        String loginName = UserIdThread.get().getLoginName();
//        String companyId = UserIdThread.get().getCompanyId();
//        //只取值年月日
////        LocalDateTime localDateTime = LocalDateTime.now();
//        LocalDate now = LocalDate.now();
//
//        /*生成请购单号*/
//        //如果是一起批处理的那么请购单号是一样的，汇总和差异不相同
//        boolean hasHz = r.stream()
//                .map(LotNoRequest5::getType)
//                .anyMatch(type -> type != null && type.equals("汇总"));
//        boolean hasCy = r.stream()
//                .map(LotNoRequest5::getType)
//                .anyMatch(type -> type != null && type.equals("差异"));
//        String hzPrefix = null;
//        String cyPrefix = null;
//        String time = "yyMMddHH";
//        if (hasHz) {
//            String k = CompanyEnum.updateId(companyId) + "HZ";
//            String hzKey = "MaterialClearance/getBatchProcess" + k  + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMM"));//自增数字里面加上年月
//            String prefix = generatePrefix(hzKey, "5", time);
//            hzPrefix = k + prefix;
//        }
//        if (hasCy) {
//            String k = CompanyEnum.updateId(companyId) + "CY";
//            String cyKey = "MaterialClearance/getBatchProcess" + k  + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMM"));//自增数字里面加上年月
//            String prefix = generatePrefix(cyKey, "5", time);
//            cyPrefix = k + prefix;
//        }
//
//        //取lotGroup数据
//        String lotNo = r.get(0).getLotNo();
//        int dashIndex = lotNo.indexOf('-');
//        String lotGroup = lotNo;
//        if (dashIndex != -1) {
//            lotGroup = lotNo.substring(0, dashIndex);
//        }
//
//        /*汇总数据(只有差异的数据需要汇总操作)*/
//        //把type+lotNo+mtlNo相同的数据的数量合并
//        // 创建一个Map来存储需要合并的数据
//        Map<String, LotNoRequest5> mergeDataMap = new HashMap<>();
//        for (LotNoRequest5 l : r) {
//            l.setCompanyId(companyId);
//            // 如果是差异类型，指令+物料编码相同的数据会合并
//            String key = l.getType() + l.getLotNo()
//                    + l.getMtlNo()
//                    + l.getMtlName()
//                    + (l.getMtlColor() != null ? l.getMtlColor() : "")
//                    + (l.getMtlSpec() != null ? l.getMtlSpec() : "")
//                    + (l.getMtlUnit() != null ? l.getMtlUnit() : "");
//            LotNoRequest5 existing = mergeDataMap.get(key);
//            if (existing == null) {
//                // 如果是第一次遇到该键，则直接添加
//                mergeDataMap.put(key, l);
//            } else {
//                // 否则，合并数量
//                existing.setYQty(safeAdd(existing.getYQty(), l.getYQty()));
//                existing.setXQty(safeAdd(existing.getXQty(), l.getXQty()));
//                existing.setCyQty(safeAdd(existing.getCyQty(), l.getCyQty()));
//                existing.setTtlUsage(safeAdd(existing.getTtlUsage(), l.getTtlUsage()));
//                existing.setSubUsage(safeAdd(existing.getSubUsage(), l.getSubUsage()));
//            }
//        }
//        // 把合并后的数据加入到新的列表
//        List<LotNoRequest5> request = new ArrayList<>(mergeDataMap.values());
//        boolean b = request.stream().anyMatch(item -> item.getCyQty() != null && item.getCyQty().compareTo(BigDecimal.ZERO) <= 0);
//        if (b) {
//            throw new ServiceErrorException("有记录’计算‘后的订购数量为负数或零，请检查！");
//        }
//
//        /*填充数据*/
//        //汇总数据和差异数据
//        List<LotNoRequest5> hzList = new ArrayList<>();
//        List<LotNoRequest5> cyList = new ArrayList<>();
//        /*把差异数据和汇总数据分成两个组*/
//        for (LotNoRequest5 lotNoRequest : r) {
//            // 计算订购数量
//           lotNoRequest.setCyQty(lotNoRequest.getCyQty());
//           lotNoRequest.setTtlUsage(lotNoRequest.getYQty());
//           lotNoRequest.setLotGroup(lotGroup);
//           lotNoRequest.setCompanyId(companyId);
//           lotNoRequest.setSlipType(lotNoRequest.getType());
//
//            //生成请购单号 汇总和差异不一样
//            if (lotNoRequest.getType().equals("汇总")) {
//                lotNoRequest.setReqNo(hzPrefix);
//                hzList.add(lotNoRequest);
//            } else if (lotNoRequest.getType().equals("差异")) {
//                lotNoRequest.setSumNo(lotNoRequest.getSumNo());
//                lotNoRequest.setReqNo(cyPrefix);
//                ///如果是批处理的差异类型，请购部门写入：FLD00 业务部
////                lotNoRequest.setReqDept("FLD00");
////                lotNoRequest.setReqDeptName("业务部");
//                lotNoRequest.setSendType("送货上门");
//                lotNoRequest.setPurUserId(loginName);
//                lotNoRequest.setDiffFlag("Y");
//                cyList.add(lotNoRequest);
//            }
//        }
//
//        /*这是汇总的数据*/
//        //批处理：请购单号、请购部门、请购日期
//        for (LotNoRequest5 l : request) {
//            // 计算订购数量
//            l.setCyQty(l.getCyQty());
//            l.setTtlUsage(l.getYQty());
//            l.setLotGroup(lotGroup);
//            l.setCompanyId(companyId);
//            l.setSlipType(l.getType());
//
//            //生成请购单号 汇总和差异不一样
//            if (l.getType().equals("汇总")) {
//                l.setReqNo(hzPrefix);
////                hzList.add(l);
//            } else if (l.getType().equals("差异")) {
//                l.setSumNo(l.getSumNo());
//                l.setReqNo(cyPrefix);
//                ///如果是批处理的差异类型，请购部门写入：FLD00 业务部
//                l.setReqDept("FLD00");
//                l.setReqDeptName("业务部");
//                l.setSendType("送货上门");
//                l.setPurUserId(loginName);
//                l.setDiffFlag("Y");
////                cyList.add(l);
//            }
//        }
////        return ResponseInfo.ok();
////    }
//        try {
//            /*写入数据*/
//            //写入:材料暂收表      MP_PUR_DIS
//            int count1 = disMapper.fdPurDisAddByMClearan(request, userName, now);
//            log.info("写入:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);
//
//            //写入:材料汇总表      MP_MTL_SUM
//            int count2 = sumMapper.fdPurDisAddByMClearan(request, userName, now, loginName);
//            log.info("写入:材料汇总表      MP_MTL_SUM 成功，影响行数：{}", count2);
//
//            //写入：指令数据       MP_MTL_LOT
//            int count3 = lotMapper.fdPurDisAddByMClearan(request, userName, now);
//            log.info("写入：指令数据       MP_MTL_LOT 成功，影响行数：{}", count3);
//
//            boolean b1 = false;
//            boolean b2 = false;
//            boolean b3 = false;
//            if(ObjectUtils.isNotEmpty(hzList)){     //只有汇总数据进
//                //更新:材料汇总指令 pc042 Update
//                int count4 = summaryOperationMapper.pc042Update(hzList, userName, now,loginName);
//                b1 = count4 > 0;
//                log.info("更新:材料汇总指令 pc042 成功，影响行数：{}", count4);
//            }
//            if(ObjectUtils.isNotEmpty(cyList)){
//                //更新:   PC_LOT_USAGE_CHG    PC_LOT_USAGE_FIT_CHG
//                // 先把数据查出来
//                int count5 = pcLotUsageChgMapper.updatepcLotUsageChgByPur(cyList);
//                int count6 = pcLotUsageChgMapper.updatepcLotUsageFitChgByPur(cyList);
//                b2 = count5 > 0 || count6 > 0;
//                log.info("更新:PC_LOT_USAGE_CHG 数据更新成功，影响行数：{}", count5);
//                log.info("更新:PC_LOT_USAGE_FIT_CHG 数据更新成功，影响行数：{}", count6);
//            }
//
//            String responseMessage = "批处理成功";
//            if (hasHz && hasCy) {
//                responseMessage += ",请购单号：" + hzPrefix + "," + cyPrefix;
//                b3 = b1 && b2;
//            } else if (hasHz) {
//                responseMessage += ",请购单号：" + hzPrefix;
//                b3 = b1;
//            } else if (hasCy) {
//                responseMessage += ",请购单号：" + cyPrefix;
//                b3 = b2;
//            }
//
//            if(count1 > 0 && count2 > 0 && count3 > 0 && b3){
//                return ResponseInfo.ok(responseMessage);
//            }else{
//                throw new ServiceErrorException("批处理失败");
//            }
//        }catch (Exception e){
//            log.error("批处理过程中发生异常，请检查日志",e);
//             throw new ServiceErrorException("批处理过程中发生异常，请检查日志!");
//        }
//    }
    /**
     * 请求批处理
     */
    @Override
    @Transactional
    public ResponseInfo getBatchProcess(List<LotNoRequest5> r) {
        /*判断*/
        if (r == null || r.isEmpty()) {
            throw new ServiceErrorException("请选择要下单的数据");
        }
        //订购数量为负的，不能请购！
        boolean a = r.stream().anyMatch(item -> item.getCyQty() != null && item.getCyQty().compareTo(BigDecimal.ZERO) <= 0);
        if (a) {
            throw new ServiceErrorException("有记录订购数量为负数或零，请检查！");
        }

        /*获取基础数据*/
        String userName = UserIdThread.get().getUserName();
        String loginName = UserIdThread.get().getLoginName();
        String companyId = UserIdThread.get().getCompanyId();

        /*去查询指令物料编码有没有问题*/
        //根据指令批量
        List<String> lotNos = r.stream()
                .map(LotNoRequest5::getLotNo)                    // 提取 lotNo
                .filter(Objects::nonNull)                        // 过滤 null
                .distinct()                                      // 去重
                .sorted()                                        // 升序排序
                .collect(Collectors.toList());
        //查询 PC_LOT_USAGE 错误编码
        boolean b = false;
        List<CleanDataDto> list1 = summaryOperationMapper.cleanPcLotUsageBatch(companyId,lotNos);
        if (list1 != null && !list1.isEmpty()) {
            b = true;
        }
        //查询 SD_BOM_FIT_SUB 错误编码
        boolean c = false;
        List<CleanDataDto> list2 = summaryOperationMapper.cleanSdBomFitSub2();
        if (list2 != null && !list2.isEmpty()) {
            c = true;
        }
        //查询 PC_LOT_USAGE_FIT 错误编码
        boolean d = false;
        List<CleanDataDto> list3 = summaryOperationMapper.cleanPcLotUsageFitBatch(companyId,lotNos);
        if (list3 != null && !list3.isEmpty()) {
            d = true;
        }
        if(b || c || d){
            throw new ServiceErrorException("勾选指令存在材料编码错误，请勾选指令后点击“数据清洗”处理编码异常");
        }
        //String lotNo1 = r.get(0).getLotNo();
        ////查询 PC_LOT_USAGE 错误编码
        //boolean b = false;
        //List<CleanDataDto> list1 = summaryOperationMapper.cleanPcLotUsage(companyId,lotNo1);
        //if (list1 != null && !list1.isEmpty()) {
        //    b = true;
        //}
        ////查询 SD_BOM_FIT_SUB 错误编码
        //boolean c = false;
        //List<CleanDataDto> list2 = summaryOperationMapper.cleanSdBomFitSub(companyId,lotNo1);
        //if (list2 != null && !list2.isEmpty()) {
        //    c = true;
        //}
        ////查询 PC_LOT_USAGE_FIT 错误编码
        //boolean d = false;
        //List<CleanDataDto> list3 = summaryOperationMapper.cleanPcLotUsageFit(companyId,lotNo1);
        //if (list3 != null && !list3.isEmpty()) {
        //    d = true;
        //}
        //if(b || c || d){
        //    throw new ServiceErrorException(lotNo1 + "指令存在材料编码错误，请点击“数据清洗”按钮清洗！");
        //}

        //只取值年月日
        LocalDate now = LocalDate.now();

        /*生成请购单号*/
        //如果是一起批处理的那么请购单号是一样的，汇总和差异不相同
        boolean hasHz = r.stream()
                .map(LotNoRequest5::getType)
                .anyMatch(type -> type != null && type.equals("汇总"));

        String hzPrefix = null;
        String time = "yyMMddHH";
        if (hasHz) {
            String k = CompanyEnum.updateId(companyId) + "HZ";
            String hzKey = "MaterialClearance/getBatchProcess" + k  + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMM"));//自增数字里面加上年月
            String prefix = generatePrefix(hzKey, "5", time);
            hzPrefix = k + prefix;
        }

        //取lotGroup数据
        String lotNo = r.get(0).getLotNo();
        int dashIndex = lotNo.indexOf('-');
        String lotGroup = lotNo;
        if (dashIndex != -1) {
            lotGroup = lotNo.substring(0, dashIndex);
        }

        /*填充数据*/
        /*把差异数据和汇总数据分成两个组*/
        for (LotNoRequest5 lotNoRequest : r) {
            // 计算订购数量
            lotNoRequest.setCyQty(lotNoRequest.getCyQty());
            lotNoRequest.setTtlUsage(lotNoRequest.getCyQty());
            lotNoRequest.setLotGroup(lotGroup);
            lotNoRequest.setCompanyId(companyId);
            lotNoRequest.setSlipType(lotNoRequest.getType());
            lotNoRequest.setReqNo(hzPrefix);
        }

        try {
            /*写入数据*/
            //写入:材料暂收表      MP_PUR_DIS
            int count1 = disMapper.fdPurDisAddByMClearan(r, userName, now);
            log.info("写入:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);

            //写入:材料汇总表      MP_MTL_SUM
            int count2 = sumMapper.fdPurDisAddByMClearan(r, userName, now, loginName);
            log.info("写入:材料汇总表      MP_MTL_SUM 成功，影响行数：{}", count2);

            //写入：指令数据       MP_MTL_LOT
            int count3 = lotMapper.fdPurDisAddByMClearan(r, userName, now);
            log.info("写入：指令数据       MP_MTL_LOT 成功，影响行数：{}", count3);

            if(count1 > 0 && count2 > 0 && count3 > 0){
                return ResponseInfo.ok("请购批处理成功，请购单号：" + hzPrefix );
            }else{
                throw new ServiceErrorException("批处理失败");
            }
        }catch (Exception e){
            log.error("批处理过程中发生异常，请检查日志",e);
            throw new ServiceErrorException("批处理过程中发生异常，请检查日志!");
        }
    }

//    /**
//     * 退回（未订购订单到批处理
//     * @param request
//     * @return
//     */
//    @Override
//    @Transactional
//    public ResponseInfo sendBack(LotNoRequest6 request) {
//        /*判断*/
//        //退回未订购订单
//        if(request.getPurFlag() != null && request.getPurFlag().equals("Y")){
//            throw new ServiceErrorException("已订购不能退回");
//        }
//        /*获取基础数据*/
//        String companyId = UserIdThread.get().getCompanyId();
//        request.setCompanyId(companyId);
//
//        try {
//            /*删除数据*/
//            //删除:材料暂收表      MP_PUR_DIS
//            int count1 = disMapper.fdPurDisDelete(request);
//            log.info("删除:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);
//
//            //删除:材料汇总表      MP_MTL_SUM
//            int count2 = sumMapper.fdPurDisDelete(request);
//            log.info("删除:材料汇总表      MP_MTL_SUM 成功，影响行数：{}", count2);
//
//            //删除：指令数据       MP_MTL_LOT
//            int count3 = lotMapper.fdPurDisDelete(request);
//            log.info("删除：指令数据       MP_MTL_LOT 成功，影响行数：{}", count3);
//            //subMapper.fdPurDisAdd(request);   //只有贴合走此逻辑
//
//            boolean b1 = false;
//            boolean b2 = false;
//            boolean b3 = false;
//            //汇总的数据
//            if(request.getPurType().equals("汇总")){
////                //TODO
////                //查询情况
////                SummaryRequest r = new SummaryRequest();
////                r.setLotNo(request.getLotDetail());
////                List<SummaryMaterialsDto> list = summaryOperationMapper.summaryDataExchange3(companyId, r);
//
//                //1.更新
//                //判断订单数据是不是以前平移的单子，如果是以前的单子，且订购数量和pc042一样的，继续更新
//                //新的订购单也是继续更新
//                //更新回原先的汇总数据
//                int count4 = summaryOperationMapper.pc042UpdateBack(request);
//
//                //2.新增
//
//                b1 = count4 > 0;
//                log.info("更新:材料汇总指令 pc042 成功，影响行数：{}", count4);
//            }else{
//                //更新:   PC_LOT_USAGE_CHG    PC_LOT_USAGE_FIT_CHG
//                // 先把数据查出来
//                int count5 = pcLotUsageChgMapper.updateBackPcLotUsageChgByPur(request);
//                int count6 = pcLotUsageChgMapper.updatBackPcLotUsageFitChgByPur(request);
//                b2 = count5 > 0 || count6 > 0;
//                log.info("更新:PC_LOT_USAGE_CHG 数据更新成功，影响行数：{}", count5);
//                log.info("更新:PC_LOT_USAGE_FIT_CHG 数据更新成功，影响行数：{}", count6);
//            }
//             b3 = b1 || b2;
//
//            if(count1 > 0 && count2 > 0 && count3 > 0 && b3){
//                return ResponseInfo.ok("退回成功");
//            }else{
//                throw new ServiceErrorException("退回失败");
//            }
//        }catch (Exception e){
//            log.error("退回过程中发生异常，请检查日志",e);
//            throw new ServiceErrorException("退回请购单发生异常，请检查日志!");
//        }
//    }
    /**
     * 退回（未订购订单到批处理
     * @param request
     * @return
     */
    @Override
    @Transactional
    public ResponseInfo sendBack(LotNoRequest6 request) {
        /*判断*/
        //退回未订购订单
        if(request.getPurFlag() != null && request.getPurFlag().equals("Y")){
            throw new ServiceErrorException("已订购不能退回");
        }
        /*获取基础数据*/
        String companyId = UserIdThread.get().getCompanyId();
        request.setCompanyId(companyId);

        try {
            /*删除数据*/
            //删除:材料暂收表      MP_PUR_DIS
            int count1 = disMapper.fdPurDisDelete(request);
            log.info("删除:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);

            //删除:材料汇总表      MP_MTL_SUM
            int count2 = sumMapper.fdPurDisDelete(request);
            log.info("删除:材料汇总表      MP_MTL_SUM 成功，影响行数：{}", count2);

            //删除：指令数据       MP_MTL_LOT
            int count3 = lotMapper.fdPurDisDelete(request);
            log.info("删除：指令数据       MP_MTL_LOT 成功，影响行数：{}", count3);
            //subMapper.fdPurDisAdd(request);   //只有贴合走此逻辑

            if(count1 > 0 && count2 > 0 && count3 > 0){
                return ResponseInfo.ok("退回成功");
            }else{
                throw new ServiceErrorException("退回失败");
            }
        }catch (Exception e){
            log.error("退回过程中发生异常，请检查日志",e);
            throw new ServiceErrorException("退回请购单发生异常，请检查日志!");
        }
    }

    ///**
    // * 退回（未订购订单到批处理）-批量
    // * @param request
    // * @return
    // */
    //@Override
    //@Transactional
    //public ResponseInfo sendBackBatch(List<LotNoRequest6> request) {
    //    /*获取基础数据*/
    //    String companyId = UserIdThread.get().getCompanyId();
    //
    //    try {
    //        /*删除数据*/
    //        //1.批量删除:材料暂收表      MP_PUR_DIS
    //        int count1 = disMapper.fdPurDisDeleteBatch(request,companyId);
    //        log.info("删除:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);
    //
    //        //2.批量删除:材料汇总表      MP_MTL_SUM
    //        int count2 = sumMapper.fdPurDisDeleteBatch(request,companyId);
    //        log.info("删除:材料汇总表      MP_MTL_SUM 成功，影响行数：{}", count2);
    //
    //        //3.批量删除：指令数据       MP_MTL_LOT
    //        int count3 = lotMapper.fdPurDisDeleteBatch(request,companyId);
    //        log.info("删除：指令数据       MP_MTL_LOT 成功，影响行数：{}", count3);
    //
    //        //4.分别对要更新的汇总差异数据，以及要删除的已经下单的数据进行处理
    //        List<LotNoRequest6> hzList = new ArrayList<>(); //汇总
    //        List<LotNoRequest6> cyList = new ArrayList<>(); //差异
    //        List<LotNoRequest6> purList = new ArrayList<>(); //订购已经下单的
    //        for (LotNoRequest6 request6 : request) {
    //            if(request6.getPurType().equals("汇总")){
    //                hzList.add(request6);
    //            }else if(request6.getPurType().equals("差异")){
    //                cyList.add(request6);
    //            }
    //            //已经下单的
    //            if(request6.getPurNo() != null){
    //                purList.add(request6);
    //            }
    //        }
    //
    //        boolean b1 = false;
    //        boolean b2 = false;
    //        boolean b3 = false;
    //        boolean b4 = false;
    //        //5.处理汇总的数据、、、、汇总
    //        //批量更新回原先的汇总数据
    //        if(hzList.size() > 0){
    //            int count4 = summaryOperationMapper.pc042UpdateBackBatch(hzList,companyId);
    //            b1 = count4 > 0;
    //            log.info("更新:材料汇总指令 pc042 成功，影响行数：{}", count4);
    //        }
    //        //6.处理差异的数据、、、、差异
    //        //批量更新差异数据:   PC_LOT_USAGE_CHG    贴合的PC_LOT_USAGE_FIT_CHG
    //        if (cyList.size() > 0){
    //            int count5 = pcLotUsageChgMapper.updateBackPcLotUsageChgByPurBatch(cyList,companyId);
    //            int count6 = pcLotUsageChgMapper.updatBackPcLotUsageFitChgByPurBatch(cyList,companyId);
    //            b2 = count5 > 0 || count6 > 0;
    //            log.info("更新:PC_LOT_USAGE_CHG 数据更新成功，影响行数：{}", count5);
    //            log.info("更新:PC_LOT_USAGE_FIT_CHG 数据更新成功，影响行数：{}", count6);
    //        }
    //        b3 = b1 || b2;
    //
    //        //5.只有已经下单的走这条路******
    //        //5.批量删除：材料指令订购单 MP_PUR_MTL_LOT
    //        if(purList.size() > 0){
    //            int count7 = mtlLotMapper.deletePurBatch(purList,companyId);
    //            b4 = count7 > 0;
    //            log.info("删除：材料指令订购单       MP_PUR_MTL_LOT 成功，影响行数：{}", count7);
    //        }
    //
    //        if (purList.size() > 0) {
    //            boolean success = count1 > 0 && count2 > 0 && count3 > 0 && b3 && b4;
    //            if (success) {
    //                return ResponseInfo.ok("批量退回成功");
    //            } else {
    //                throw new ServiceErrorException("批量退回失败");
    //            }
    //        } else {
    //            boolean success = count1 > 0 && count2 > 0 && count3 > 0 && b3 ;
    //            if (success) {
    //                return ResponseInfo.ok("批量退回成功");
    //            } else {
    //                throw new ServiceErrorException("批量退回失败");
    //            }
    //        }
    //
    //
    //    }catch (Exception e){
    //        log.error("退回过程中发生异常，请检查日志",e);
    //        throw new ServiceErrorException("批量退回请购单发生异常，请检查日志!");
    //    }
    //}
    /**
     * 退回（未订购订单到批处理）-批量
     * @param request
     * @return
     */
    @Override
    @Transactional
    public ResponseInfo sendBackBatch(List<LotNoRequest6> request) {
        /*获取基础数据*/
        String companyId = UserIdThread.get().getCompanyId();

        try {
            /*删除数据*/
            //1.批量删除:材料暂收表      MP_PUR_DIS
            int count1 = disMapper.fdPurDisDeleteBatch(request,companyId);
            log.info("删除:材料暂收表      MP_PUR_DIS 成功，影响行数：{}", count1);

            //2.批量删除:材料汇总表      MP_MTL_SUM
            int count2 = sumMapper.fdPurDisDeleteBatch(request,companyId);
            log.info("删除:材料汇总表      MP_MTL_SUM 成功，影响行数：{}", count2);

            //3.批量删除：指令数据       MP_MTL_LOT
            int count3 = lotMapper.fdPurDisDeleteBatch(request,companyId);
            log.info("删除：指令数据       MP_MTL_LOT 成功，影响行数：{}", count3);

            //4.分别对要更新的汇总差异数据，以及要删除的已经下单的数据进行处理
            List<LotNoRequest6> purList = new ArrayList<>(); //订购已经下单的
            for (LotNoRequest6 request6 : request) {
                //已经下单的
                if(request6.getPurNo() != null){
                    purList.add(request6);
                }
            }

            boolean b4 = false;

            //5.只有已经下单的走这条路******
            //5.批量删除：材料指令订购单 MP_PUR_MTL_LOT
            if(purList.size() > 0){
                int count7 = mtlLotMapper.deletePurBatch(purList,companyId);
                b4 = count7 > 0;
                log.info("删除：材料指令订购单       MP_PUR_MTL_LOT 成功，影响行数：{}", count7);
            }

            if (purList.size() > 0) {
                boolean success = count1 > 0 && count2 > 0 && count3 > 0  && b4;
                if (success) {
                    return ResponseInfo.ok("批量退回成功");
                } else {
                    throw new ServiceErrorException("批量退回失败");
                }
            } else {
                boolean success = count1 > 0 && count2 > 0 && count3 > 0  ;
                if (success) {
                    return ResponseInfo.ok("批量退回成功");
                } else {
                    throw new ServiceErrorException("批量退回失败");
                }
            }


        }catch (Exception e){
            log.error("退回过程中发生异常，请检查日志",e);
            throw new ServiceErrorException("批量退回请购单发生异常，请检查日志!");
        }
    }

    /**
     * 导出订购单
     * @param response
     */
    @Override
    public void exportPurchaseOrder(String purNo, HttpServletResponse response) {
        /*设定默认的文件名字*/
        String fileName = "材料订购单" +DateUtils.dateTimeNow() + ".xlsx";

        /*查询表中公共数据*/
        //公司信息
        SysUserTokenDTO sysUserTokenDTO = UserIdThread.get();
        String companyId = sysUserTokenDTO.getCompanyId();
        PurCompany2 companyDto = purMapper2.findPurCompanyInfo(companyId,"面材");
        //制表时间
        DateTimeFormatter sdf2 = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        String sysDate = LocalDateTime.now().format(sdf2);

        /*填充默认公共的数据*/
        HashMap<String, Object> map = new HashMap<>();
        map.put("c", companyDto);
        map.put("s", sysUserTokenDTO);
        map.put("sysDate",sysDate);

        if(StringUtils.isNotBlank(purNo)){
            // 查询该订单号的所有数据
            PurchaseOrderRequest request = new PurchaseOrderRequest();
            request.setCompanyId(companyId);
            request.setPurNo(purNo);
            List<PurchaseOrderDto> list = materialClearanceMapper.getPurchaseOrderInHzAndCyOrderByLot(request);
            if(ObjectUtils.isNotEmpty(list) && list.size() > 0){
                //该订单号的数据
                PurchaseOrderDto dto = list.get(0);

                // 厂商信息
                String vendorName = dto.getVendorName() != null ? dto.getVendorName() : "";
                SdVendor vendorDto = backMapper.getVendorNameByNo(dto.getVendorNo(), sysUserTokenDTO.getCompanyId());

                // 文件名构建
                SimpleDateFormat sdf1 = new SimpleDateFormat("yyMMdd");
                String date = dto.getPurDate() != null ? sdf1.format( dto.getPurDate()) : "";
                fileName = vendorName + date + "_" + "材料订购单" +DateUtils.dateTimeNow() + ".xlsx";

                //时间变换
                SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
                String purDate = format.format(dto.getPurDate());
                String inDate = format.format(dto.getInDate());

                //取出鞋带的信息，根据指令+材料去查询鞋码的size和预补数量
                Set<PurchaseOrderDto> shoelaceList = list.stream()
                        .filter(item -> item.getMtlNo().substring(0, 2).equals("J8"))
                        .collect(Collectors.toSet());
                Map<String, PcLotUsageDto> usageMap = new HashMap<>();
                if(ObjectUtils.isNotEmpty(shoelaceList)){
                    List<PcLotUsageDto> usageDetails = pcLotHeadMapper.getUsageDetailsByLotAndMtlBatch(shoelaceList);
                    // 构建一个基于材料编号的快速查找映射
                    usageMap = usageDetails.stream()
                            .collect(Collectors.toMap(
                                    item -> String.join("-",
                                            Objects.toString(item.getLotNo(), ""),
                                            Objects.toString(item.getMtlName(), ""),
                                            Objects.toString(item.getMtlColor(), ""),
                                            Objects.toString(item.getMtlSpec(), ""),
                                            Objects.toString(item.getMtlUnit(), "")),
                                    item -> item,
                                    (existing, replacement) -> existing // 冲突解决策略，保留现有值
                            ));
                }

                Float count = 0.0f;
                for (PurchaseOrderDto t : list) {
                    //判断是否有英文名字，有的话就拼接
                    String name = null;
                    if(t.getEngColor() == null || t.getEngColor().equals("")){
                        name = t.getMtlColor() + "/" + t.getMtlName();
                    }else{
                        name = t.getEngColor() + "/" +t.getMtlColor() + "/" + t.getMtlName() ;
                    }
                    t.setMtlColorAndName(name);

                    //根据材料匹配鞋带的号码和预补数量
                    if ("J8".equals(t.getMtlNo().substring(0, 2))) {
                        String key = String.join("-",
                                Objects.toString(t.getLotDetail(), ""),
                                Objects.toString(t.getMtlName(), ""),
                                Objects.toString(t.getMtlColor(), ""),
                                Objects.toString(t.getMtlSpec(), ""),
                                Objects.toString(t.getMtlUnit(), ""));
                        PcLotUsageDto usageDto = usageMap.get(key);
                        if (usageDto != null) {
                            name += "(" + usageDto.getSize1() + "-" + usageDto.getSize2() + ")";
                            t.setMtlColorAndName(name);
                            t.setPrefill(usageDto.getSurplusQty());
                        }
                    }

                    if (!ObjectUtils.isEmpty(t.getPurQty())) {
                        count = count + t.getPurQty();
                    }

                    //不写了，采购部自己手动加预补数量
//                    //只有眼扣，鸡眼扣，金属扣，铁扣，鞋带锁扣等5种扣子要预补数量
//                    if(t.getMtlUnit().equals("SF") || t.getMtlUnit().equals("Y")){
//                        BigDecimal prefill = t.getPrefill();
//                        BigDecimal decimal = roundOrHalfQty(prefill);
//                        t.setPrefill(decimal);
//                    }else{
//                        t.setPrefill(null);
//                    }
                }
                //填充模板数据
                map.put("mapList", list);
                map.put("p", dto);
                map.put("v", vendorDto);
                map.put("count", count);
                map.put("purDate",purDate);
                map.put("inDate",inDate);
            }

        }

        try {
            ExcelUtils.setResponseZF(response, fileName);
            String templatePath = StringUtils.isNotBlank(purNo) ? "templates/订购单-材料清购.xls" : "templates/订购单-材料清购无数据.xls";
            ExcelPoiUtils.writeExcelList(response, map, templatePath, fileName);
        } catch (Exception e) {
            log.error("材料订购单导出失败, 错误信息: {}", e.getMessage());
            throw new ServiceErrorException("导出订购单失败");
        }
    }

    /**
     * 导出分码订购单
     * @param purNo
     * @param response
     */
    @Override
    public void exportSziePurchaseOrder(String purNo, HttpServletResponse response) {

        //判断>>订购单号不能为空
        if (purNo == null) {
            throw new ServiceErrorException("订购单号不能为空");
        }

         /*模板*/
        //用来装中间数据
        List<List<String>> allDateList = new ArrayList<>();
        //用来装模板数据
        HashMap<String, Object> map = new HashMap<>();
        //文件名构建
        String fileName = "分码订购单" +DateUtils.dateTimeNow() + ".xlsx";

        //*查询所有订购单数据*/
        //构建查询参数
        SysUserTokenDTO sysUserTokenDTO = UserIdThread.get();
        PurchaseOrderRequest request = new PurchaseOrderRequest();
        String companyId = sysUserTokenDTO.getCompanyId();
        request.setCompanyId(companyId);
        request.setPurNo(purNo);
        //查询该订购单号数据
        List<PurchaseOrderDto> dtoList = materialClearanceMapper.getPurchaseOrderInHzAndCy(request);
        //查询分组lotNo+mtlNo相同的
        List<PurchaseOrderDto> list = materialClearanceMapper.getPurchaseOrderInHzAndCy2(request);

        if(ObjectUtils.isNotEmpty(dtoList) && dtoList.size() > 0){
            //模板上其他数据
            PurchaseOrderDto dto = dtoList.get(0);
            //公司
            PurCompany2 companyDto = purMapper2.findPurCompanyInfo(sysUserTokenDTO.getCompanyId(),"面材");
            // 厂商信息
            SdVendor vendorDto = backMapper.getVendorNameByNo(dto.getVendorNo(), companyId);
            String vendorName = dto.getVendorName() != null ? dto.getVendorName() : "";

            // 文件名构建
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyMMdd");
            String date = dto.getPurDate() != null ? sdf1.format( dto.getPurDate()) : "";
            fileName = vendorName + date + "_" + "材料分码订购单" +DateUtils.dateTimeNow() + ".xlsx";

            if (ObjectUtils.isNotEmpty(list)){
                for (PurchaseOrderDto orderDto : list) {
                    //根据指令单号查询出他的预补号数量这些
                    List<PcLotDetailDto> codeDetails = pcLotHeadMapper.getCodeDetails3(orderDto.getLotDetail(),companyId);

                    BigDecimal orderQtyCount = BigDecimal.ZERO;;
                    BigDecimal surplusQtyCount = BigDecimal.ZERO;;

                    for (int i = 0; i < 6; i++) {
                        List<String> dateList = new ArrayList<>();
                        dateList.add(orderDto.getLotDetail());
                        dateList.add(orderDto.getMtlColor() + "/" +  orderDto.getMtlName() );
                        dateList.add(orderDto.getMtlSpec());

                        if(i==0) {
                            dateList.add("鞋码");
                        }else if(i==1) {
                            dateList.add("大底");
                        }else if(i==2) {
                            dateList.add("冲刀");
                        }else if(i==3) {
                            dateList.add("楦头");
                        }else if(i==4) {
                            dateList.add("订单数");
                        }else if(i==5) {
                            dateList.add("预补数");
                        }

                        for (PcLotDetailDto codeDetail : codeDetails) {
                            if(i==0) {
                                dateList.add(codeDetail.getSizeNo());
                            }else if(i==1) {
                                dateList.add(codeDetail.getSoleSize());
                            }else if(i==2) {
                                dateList.add(codeDetail.getCutSize());
                            }else if(i==3) {
                                dateList.add(codeDetail.getLastSize());
                            }else if(i==4) {
                                dateList.add(Objects.toString(codeDetail.getOrderQty(), ""));
                                if (codeDetail.getOrderQty() != null) {
                                    orderQtyCount = orderQtyCount.add(codeDetail.getOrderQty());
                                }
                            }else if(i==5) {
                                dateList.add(Objects.toString(codeDetail.getSurplusQty(), ""));
                                if (codeDetail.getSurplusQty() != null) {
                                    surplusQtyCount = surplusQtyCount.add(codeDetail.getSurplusQty());
                                }
                            }
                        }

                        if(i==4) {
                            String count = orderQtyCount!= null ? orderQtyCount.toString(): "";
                            insertValuesAndShift(dateList, 30, new String[]{count});
                        }else if(i==5) {
                            String count = surplusQtyCount!= null ? surplusQtyCount.toString(): "";
                            insertValuesAndShift(dateList, 30, new String[]{count});
                        }else{
                            insertValuesAndShift(dateList, 30, new String[]{""});
                        }

                        allDateList.addAll(Arrays.asList(dateList));
                    }

                }
            }

            //填充模板上的数据
            map.put("purDate",dto.getPurDate());
            map.put("inDate",dto.getInDate());
            map.put("purNo", purNo);
            map.put("c", companyDto);
            map.put("s", sysUserTokenDTO);
            map.put("v", vendorDto);
            map.put("p", dto);
//        map.put("sizeDtoList", sizeDtoList);

        }

        //获取模板
        TemplateExportParams templateParams = new TemplateExportParams("templates/分码订购单模板.xls");
        //开启横向遍历 开启横向遍历 开启横向遍历
        templateParams.setColForEach(true);
        //字体样式
        CellStyleBuild cellStyle = new CellStyleBuild();
        cellStyle.setFontName("微软雅黑");
        cellStyle.setFontSize((short) 11);
        ArrayList<Integer> headerRowIndexList = new ArrayList<>();

        try{
        ExcelUtils.setResponseZF(response, fileName);
        ExcelPoiUtils.writeExcelList222(response, map, allDateList,
                templateParams,
                3, 0,32,headerRowIndexList,
                cellStyle,cellStyle,false,null);
        } catch (Exception e) {
            log.error("材料分码订购单导出失败, 错误信息: {}", e.getMessage());
            throw new ServiceErrorException(e.getMessage());
        }

    }


    /**
     * 获得时间戳+自增数据
     * @param key  根据key获得自增数据
     * @param length 自增长度
     * @param timezone 想要获得的时间戳保留字段 yyMM yyyy-MM-dd HH:mm:ss
     */
    private String generatePrefix(String key,String length,String timezone) {
        //根据key获得自增数据
        RedisAtomicInteger ato = new RedisAtomicInteger(key, redisService.getConnectionFactory());
        String l = "%0" + length + "d"; //%07d
        String value = String.format(l, ato.getAndIncrement());
        redisService.setOutTime(key);
        //时间戳
        LocalDateTime now = LocalDateTime.now();
        String time = now.format(DateTimeFormatter.ofPattern(timezone));
        return time + value;
    }

    /**
     * 在指定位置插入新元素，并将原有数据向后移动。
     * @param list         要处理的列表
     * @param insertIndex  插入元素的起始索引（例如，要插入在第15列，则该值为14）
     * @param values       要插入的值数组
     */
    public void insertValuesAndShift(List<String> list, int insertIndex, String[] values) {
        // 确保插入索引不会超出范围
        while (list.size() <= insertIndex) {
            // 如果插入索引超过当前列表长度，则添加空字符串直到达到插入索引
            list.add("");
        }

        // 创建一个临时列表来保存插入索引及以后的数据
        List<String> tempList = new ArrayList<>(list.subList(insertIndex, list.size()));

        // 清空插入索引及以后的数据
        list.subList(insertIndex, list.size()).clear();

        // 插入指定的值
        for (String value : values) {
            list.add(insertIndex++, value);
        }

        // 从插入索引开始继续添加临时列表中的数据
        list.addAll(insertIndex, tempList);
    }


    /*将BigDecimal判空*/
    private  BigDecimal safeAdd(BigDecimal a, BigDecimal b) {
        // 将null值转换为BigDecimal.ZERO
        a = a != null ? a : BigDecimal.ZERO;
        b = b != null ? b : BigDecimal.ZERO;
        return a.add(b);
    }

    /*将数量四舍五入*/
    public BigDecimal roundOrHalfQty(BigDecimal prefill){
        //预补数量要向上取整，四舍五入
        if(prefill != null){
            // 获取整数部分
            BigDecimal intPart = prefill.setScale(0, BigDecimal.ROUND_DOWN);
            // 获取小数部分
            BigDecimal pointPart = prefill.subtract(intPart);
            if(pointPart.compareTo(BigDecimal.valueOf(0.0)) == 0 || pointPart.compareTo(BigDecimal.valueOf(0.5)) == 0){
                prefill = prefill;
            }else{
                int result = pointPart.compareTo(BigDecimal.valueOf(0.5));
                if(result > 0){
                    prefill = intPart.add(BigDecimal.valueOf(1));
                }else if(result < 0){
                    prefill = intPart.add(BigDecimal.valueOf(0.5));
                }
            }

        }else{
            prefill = null;
        }
        return prefill;
    }

}
